import java.util.ArrayList;
import java.util.List;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.Map;
import java.util.AbstractMap.SimpleImmutableEntry;

public class Parser {
    private String input;
    private int pos;
    private char currentChar;
    private static final Map<String, TokenType> KEYWORDS;
    private static final Map<Character, TokenType> SYMBOLS;

    static {
        SYMBOLS = Map.ofEntries(
                new SimpleImmutableEntry<>('=', TokenType.ASSIGN), new SimpleImmutableEntry<>(';', TokenType.SEMICOLON),
                new SimpleImmutableEntry<>('(', TokenType.LEFT_PAREN), new SimpleImmutableEntry<>(')', TokenType.RIGHT_PAREN),
                new SimpleImmutableEntry<>('{', TokenType.LEFT_BRACE), new SimpleImmutableEntry<>('}', TokenType.RIGHT_BRACE),
                new SimpleImmutableEntry<>('+', TokenType.PLUS), new SimpleImmutableEntry<>('-', TokenType.MINUS),
                new SimpleImmutableEntry<>('*', TokenType.MUL), new SimpleImmutableEntry<>('/', TokenType.DIV),
                new SimpleImmutableEntry<>('<', TokenType.LT), new SimpleImmutableEntry<>('>', TokenType.GT)
        );
    }

    static {
        KEYWORDS = Map.ofEntries(
                new SimpleImmutableEntry<>("if", TokenType.IF), new SimpleImmutableEntry<>("else", TokenType.ELSE),
                new SimpleImmutableEntry<>("while", TokenType.WHILE),
                new SimpleImmutableEntry<>("break", TokenType.BREAK),
                new SimpleImmutableEntry<>("continue", TokenType.CONTINUE),
                new SimpleImmutableEntry<>("return", TokenType.RETURN)
        );
    }

    public Parser(String input) {
        this.input = input;
        this.pos = 0;
        this.currentChar = pos < input.length() ? input.charAt(pos) : '\0';
    }

    private void advance() {
        pos++;
        currentChar = pos < input.length() ? input.charAt(pos) : '\0';
    }

    private boolean isLetter(char ch) {
        return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
    }

    private boolean isDigit(char ch) {
        return ch >= '0' && ch <= '9';
    }

    private boolean isUnderline(char ch) {
        return ch == '_';
    }

    private Token identifier() {
        StringBuilder result = new StringBuilder();
        while (currentChar != '\0' && (isLetter(currentChar) || isDigit(currentChar) || isUnderline(currentChar))) {
            result.append(currentChar);
            advance();
        }
        String id = result.toString();
        TokenType type = KEYWORDS.getOrDefault(id, TokenType.IDENTIFIER);
        return new Token(type, id);
    }

    private Token integer() {
        StringBuilder result = new StringBuilder();
        while (currentChar != '\0' && isDigit(currentChar)) {
            result.append(currentChar);
            advance();
        }
        // 如果数字后面是字母！
        if (currentChar != '\0' && isLetter(currentChar)) {
            return error();
        }
        return new Token(TokenType.INTEGER, result.toString());
    }

    private Token error() {
        // 可以根据需要扩展错误处理逻辑
        return new Token(TokenType.ERR, String.valueOf(currentChar));
    }

    private Token singleCharOrDoubleCharToken() {
        TokenType type;
        String value = String.valueOf(currentChar);

        if (currentChar == '=') {
            advance();
            if (currentChar == '=') {
                type = TokenType.EQ;
                value += "=";
                advance();
            } else {
                type = TokenType.ASSIGN;
            }
        } else {
            type = SYMBOLS.getOrDefault(currentChar, TokenType.ERR);
            advance();
        }

        return new Token(type, value);
    }


    public List<Token> tokenize() {
        List<Token> tokens = new ArrayList<>();

        while (currentChar != '\0') {
            if (isLetter(currentChar) || isUnderline(currentChar)) {
                tokens.add(identifier());
            } else if (isDigit(currentChar)) {
                tokens.add(integer());
            } else if (SYMBOLS.containsKey(currentChar) || currentChar == '=') {
                tokens.add(singleCharOrDoubleCharToken());
            } else if (currentChar <= ' ') { // 跳过空白字符
                advance();
            } else {
                tokens.add(error());
                advance();
                break;
            }
        }

        return tokens;
    }

    public static void main(String[] args) {
        try {
            String content = new String(Files.readAllBytes(Paths.get("input.txt")));
            Parser parser = new Parser(content);
            List<Token> tokens = parser.tokenize();
            for (Token token : tokens) {
                System.out.println(token);
                if (token.type == TokenType.ERR) {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class Token {
    TokenType type;
    String value;

    Token(TokenType type, String value) {
        this.type = type;
        this.value = value;
    }

    @Override
    public String toString() {
        if (type == TokenType.IDENTIFIER || type == TokenType.INTEGER) {
            return String.format("%s(%s)", type.getName(), value);
        }
        else {
            return type.getName();
        }
    }
}

